"""
Flask应用主文件
"""
import os
import logging
from flask import Flask, request, jsonify, render_template
from flask_socketio import SocketIO, emit
import asyncio
import threading
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime

from backend.utils.config import config
from backend.models.core import Question, ExecutionSession
from backend.models.session_manager import session_manager
from backend.services.question_analyzer import question_analyzer
from backend.services.cot_generator import cot_generator
from backend.services.task_manager import task_manager
from backend.services.ai_coordinator import ai_coordinator
from shared.enums import ComplexityLevel, ExecutionPath, SessionStatus

logger = logging.getLogger(__name__)


def run_async_in_thread(coro):
    """在新线程中运行异步函数"""
    def run_in_new_loop():
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        try:
            return loop.run_until_complete(coro)
        finally:
            loop.close()
    
    thread = threading.Thread(target=run_in_new_loop)
    thread.start()
    return thread


def create_app():
    """创建Flask应用"""
    # 获取模板和静态文件路径
    template_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'frontend', 'templates')
    static_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'frontend', 'static')
    
    app = Flask(__name__, template_folder=template_dir, static_folder=static_dir)
    app.config['SECRET_KEY'] = config.app.secret_key
    
    # 初始化SocketIO
    socketio = SocketIO(app, cors_allowed_origins="*", async_mode='threading')
    
    # 注册事件回调
    register_coordinator_callbacks(socketio)
    
    # 注册路由
    register_routes(app)
    register_socketio_events(socketio)
    
    return app, socketio


def register_coordinator_callbacks(socketio):
    """注册协调器事件回调"""
    
    async def on_execution_started(data):
        socketio.emit('execution_started', data)
    
    async def on_task_started(data):
        socketio.emit('task_started', data)
    
    async def on_task_completed(data):
        socketio.emit('task_completed', data)
    
    async def on_execution_completed(data):
        socketio.emit('execution_completed', data)
    
    async def on_execution_failed(data):
        socketio.emit('execution_failed', data)
    
    ai_coordinator.add_event_callback('execution_started', on_execution_started)
    ai_coordinator.add_event_callback('task_started', on_task_started)
    ai_coordinator.add_event_callback('task_completed', on_task_completed)
    ai_coordinator.add_event_callback('execution_completed', on_execution_completed)
    ai_coordinator.add_event_callback('execution_failed', on_execution_failed)


def register_routes(app):
    """注册HTTP路由"""
    
    @app.route('/')
    def index():
        """主页"""
        return render_template('index.html')
    
    @app.route('/api/health')
    def health_check():
        """健康检查"""
        return jsonify({
            'status': 'healthy',
            'timestamp': datetime.now().isoformat(),
            'sessions': session_manager.get_session_count()
        })
    
    @app.route('/api/questions', methods=['POST'])
    def submit_question():
        """提交问题"""
        try:
            data = request.get_json()
            if not data or 'content' not in data:
                return jsonify({'error': '问题内容不能为空'}), 400
            
            question_content = data['content'].strip()
            if not question_content:
                return jsonify({'error': '问题内容不能为空'}), 400
            
            # 创建问题
            question = Question(
                content=question_content,
                user_id=data.get('user_id')
            )
            
            # 创建会话
            session = session_manager.create_session(question.id)
            session.question = question
            session.status = SessionStatus.ANALYZING
            session_manager.update_session(session)
            
            # 在线程池中处理问题分析
            executor = ThreadPoolExecutor(max_workers=1)
            executor.submit(run_async_in_thread, process_question_async(session.id, question_content))
            
            return jsonify({
                'session_id': session.id,
                'question_id': question.id,
                'status': 'analyzing'
            })
            
        except Exception as e:
            logger.error(f"Question submission error: {e}")
            return jsonify({'error': '提交问题时发生错误'}), 500
    
    @app.route('/api/sessions/<session_id>')
    def get_session(session_id):
        """获取会话信息"""
        try:
            session = session_manager.get_session(session_id)
            if not session:
                return jsonify({'error': '会话不存在'}), 404
            
            return jsonify(session.to_dict())
            
        except Exception as e:
            logger.error(f"Get session error: {e}")
            return jsonify({'error': '获取会话信息失败'}), 500
    
    @app.route('/api/tasks/<session_id>', methods=['PUT'])
    def manage_tasks(session_id):
        """管理任务"""
        try:
            session = session_manager.get_session(session_id)
            if not session:
                return jsonify({'error': '会话不存在'}), 404
            
            data = request.get_json()
            if not data or 'command' not in data:
                return jsonify({'error': '缺少命令参数'}), 400
            
            # 在线程池中处理任务管理
            executor = ThreadPoolExecutor(max_workers=1)
            executor.submit(run_async_in_thread, manage_tasks_async(session_id, data['command']))
            
            return jsonify({'status': 'processing'})
            
        except Exception as e:
            logger.error(f"Task management error: {e}")
            return jsonify({'error': '任务管理失败'}), 500
    
    @app.route('/api/execution/<session_id>/start', methods=['POST'])
    def start_execution(session_id):
        """开始执行"""
        try:
            session = session_manager.get_session(session_id)
            if not session:
                return jsonify({'error': '会话不存在'}), 404
            
            if session.status not in [SessionStatus.WAITING_CONFIRMATION, SessionStatus.TASK_PLANNING]:
                return jsonify({'error': '会话状态不允许执行'}), 400
            
            # 在线程池中执行任务
            executor = ThreadPoolExecutor(max_workers=1)
            if session.execution_path == ExecutionPath.DIRECT:
                executor.submit(run_async_in_thread, execute_simple_question_async(session_id))
            else:
                executor.submit(run_async_in_thread, execute_task_sequence_async(session_id))
            
            return jsonify({'status': 'started'})
            
        except Exception as e:
            logger.error(f"Execution start error: {e}")
            return jsonify({'error': '启动执行失败'}), 500
    
    @app.route('/api/execution/<session_id>/cancel', methods=['POST'])
    def cancel_execution(session_id):
        """取消执行"""
        try:
            session = session_manager.get_session(session_id)
            if not session:
                return jsonify({'error': '会话不存在'}), 404
            
            session.status = SessionStatus.CANCELLED
            session.completed_at = datetime.now()
            session_manager.update_session(session)
            
            return jsonify({'status': 'cancelled'})
            
        except Exception as e:
            logger.error(f"Execution cancel error: {e}")
            return jsonify({'error': '取消执行失败'}), 500
    
    @app.route('/api/execution/<session_id>/status')
    def get_execution_status(session_id):
        """获取执行状态"""
        try:
            # 在新的事件循环中执行监控
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            try:
                status = loop.run_until_complete(ai_coordinator.monitor_execution(session_id))
                return jsonify(status)
            finally:
                loop.close()
            
        except Exception as e:
            logger.error(f"Get execution status error: {e}")
            return jsonify({'error': '获取执行状态失败'}), 500


def register_socketio_events(socketio):
    """注册WebSocket事件"""
    
    @socketio.on('connect')
    def handle_connect():
        logger.info('Client connected')
        emit('connected', {'status': 'success'})
    
    @socketio.on('disconnect')
    def handle_disconnect():
        logger.info('Client disconnected')
    
    @socketio.on('join_session')
    def handle_join_session(data):
        """加入会话"""
        session_id = data.get('session_id')
        if session_id:
            # 可以实现房间功能，让客户端只接收特定会话的事件
            logger.info(f'Client joined session: {session_id}')
            emit('session_joined', {'session_id': session_id})


# 异步处理函数
async def process_question_async(session_id: str, question_content: str):
    """异步处理问题分析"""
    try:
        session = session_manager.get_session(session_id)
        if not session:
            return
        
        # 分析问题
        analysis = await question_analyzer.analyze_with_ai(question_content)
        session.analysis = analysis
        
        # 根据复杂度决定执行路径
        if analysis.complexity == ComplexityLevel.SIMPLE:
            session.execution_path = ExecutionPath.DIRECT
            session.status = SessionStatus.WAITING_CONFIRMATION
        else:
            session.execution_path = ExecutionPath.TASK_BASED
            session.status = SessionStatus.TASK_PLANNING
            
            # 生成任务
            tasks = await cot_generator.generate_tasks(question_content, analysis)
            session.tasks = tasks
            session.status = SessionStatus.WAITING_CONFIRMATION
        
        session_manager.update_session(session)
        
        # 通知客户端
        from backend.api.app import socketio_instance
        if socketio_instance:
            socketio_instance.emit('question_analyzed', {
                'session_id': session_id,
                'analysis': analysis.to_dict(),
                'execution_path': session.execution_path.value,
                'tasks': [task.to_dict() for task in session.tasks]
            })
        
    except Exception as e:
        logger.error(f"Async question processing error: {e}")


async def manage_tasks_async(session_id: str, command: str):
    """异步处理任务管理"""
    try:
        session = session_manager.get_session(session_id)
        if not session:
            return
        
        # 解析和执行命令
        task_command = await task_manager.parse_task_command(command, session.tasks)
        result = await task_manager.execute_task_command(task_command, session.tasks)
        
        if result.success and result.updated_tasks:
            session.tasks = result.updated_tasks
            session_manager.update_session(session)
        
        # 通知客户端
        from backend.api.app import socketio_instance
        if socketio_instance:
            socketio_instance.emit('task_management_result', {
                'session_id': session_id,
                'success': result.success,
                'message': result.message,
                'tasks': [task.to_dict() for task in session.tasks]
            })
        
    except Exception as e:
        logger.error(f"Async task management error: {e}")


async def execute_simple_question_async(session_id: str):
    """异步执行简单问题"""
    try:
        session = session_manager.get_session(session_id)
        if not session or not session.question:
            return
        
        result = await ai_coordinator.execute_simple_question(session.question.content)
        
        if result.success:
            session.final_answer = result.result
            session.status = SessionStatus.COMPLETED
        else:
            session.status = SessionStatus.FAILED
        
        session.completed_at = datetime.now()
        session.total_tokens_used = result.tokens_used
        session_manager.update_session(session)
        
    except Exception as e:
        logger.error(f"Async simple question execution error: {e}")


async def execute_task_sequence_async(session_id: str):
    """异步执行任务序列"""
    try:
        await ai_coordinator.execute_task_sequence(session_id)
    except Exception as e:
        logger.error(f"Async task sequence execution error: {e}")


# 全局变量存储socketio实例，用于异步回调
socketio_instance = None

def create_app_with_socketio():
    """创建应用并返回socketio实例"""
    app, socketio = create_app()
    global socketio_instance
    socketio_instance = socketio
    return app, socketio